package cn.mw.cmdb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.mw.cmdb.entity.*;
import cn.mw.cmdb.enums.*;
import cn.mw.cmdb.mongoMapper.InstanceMonitorMapper;
import cn.mw.cmdb.param.*;
import cn.mw.cmdb.param.zabbixResult.*;
import cn.mw.cmdb.processor.MonitorParamContext;
import cn.mw.cmdb.processor.MonitorProcessor;
import cn.mw.cmdb.service.MwAssetsTypeMonitorLayout;
import cn.mw.cmdb.service.MwMonitorProcessorConvert;
import cn.mw.cmdb.service.handler.monitorData.HistoryHandlerProcessor;
import cn.mw.cmdb.service.handler.monitorData.MonitorHistoryHandlerFactory;
import cn.mw.cmdb.util.CMDBTool;
import cn.mw.cmdb.util.ExportExcel;
import cn.mw.cmdb.util.ListSortUtil;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.components.mongodb.entity.SubCondition;
import cn.mw.components.mongodb.page.MWPage;
import cn.mw.components.mongodb.tool.CriteriaWrapper;
import cn.mw.main.api.common.ZabbixDubboService;
import cn.mw.microMonitorCommon.api.cmdb.TableIdEnum;
import cn.mw.microMonitorCommon.api.common.MwSyncEngineCommonService;
import cn.mw.microMonitorCommon.constants.ZabbixApiConstants;
import cn.mw.microMonitorCommon.constants.ZabbixItemConstant;
import cn.mw.microMonitorCommon.entity.UnitResult;
import cn.mw.microMonitorCommon.entity.common.MwSyncEngineDto;
import cn.mw.microMonitorCommon.entity.zabbix.ApplicationDTO;
import cn.mw.microMonitorCommon.entity.zabbix.MWZabbixAPIResult;
import cn.mw.microMonitorCommon.security.dto.MwUser;
import cn.mw.microMonitorCommon.security.utils.SecurityUtils;
import cn.mw.microMonitorCommon.util.*;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.util.Pair;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.MwLayoutLabelInfo.overView;
import static cn.mw.cmdb.enums.AvailableInfoEnum.*;
import static cn.mw.cmdb.enums.BusynessSystemUtilizationEnum.*;
import static cn.mw.cmdb.enums.ChartTypeEnum.line;
import static cn.mw.cmdb.enums.ChartTypeEnum.rateLine;
import static cn.mw.cmdb.enums.DefaultMonitorTabEnum.monitorTarget;
import static cn.mw.cmdb.enums.MwDeviceTypeEnum.*;
import static cn.mw.cmdb.enums.VirtualizationTypeEnum.VCENTER;
import static cn.mw.cmdb.enums.VirtualizationTypeEnum.getVirtualizationType;
import static cn.mw.cmdb.service.handler.monitorData.MonitorHandlerUtils.historyParamConvert;
import static cn.mw.cmdb.service.impl.InstanceViewImpl.idKey;
import static cn.mw.cmdb.service.impl.InstanceViewImpl.mw_templateName;
import static cn.mw.cmdb.util.CMDBTool.getExcelExportFieldInfo;
import static cn.mw.cmdb.util.CustomPageUtil.getCustomPageInfo;
import static cn.mw.cmdb.util.ItemNameFilterUtil.itemNameFilter;
import static cn.mw.cmdb.util.ItemNameFilterUtil.itemNameFilterBracket;
import static cn.mw.cmdb.util.ValConvertUtil.*;
import static cn.mw.cmdb.util.ValConvertUtil.strValueConvert;

@Slf4j
public class InstanceMonitorServiceImpl extends ModelBaseServiceImpl<MwComponentLayoutInfo, Object> {

    private final String width = "8";
    public static final String normal = "NORMAL";
    public static final String normalState = "0";
    public static final String unSupported = "UNSUPPORTED";
    public static final String overview = "概览";
    public static final String allTemplateInfoKey = "allTemplateInfo";
    public static final String discoveryIdsKey = "discoveryIds";
    public static final long timeOutNum = 3l;

    private static CmdbServiceManage cmdbServiceManage;
    private InstanceMonitorMapper instanceMonitorMapper;

    public ModuleIDManager moduleIDManager;

    private ZabbixDubboService zabbixDubboService;

    private MwComponentLayoutInfo shareLayoutData;

    private MwSyncEngineCommonService mwSyncEngineCommonService;


    public static final String ID = "instanceMonitor";

    public static final String MW_DISK_UTILIZATION = "MW_DISK_UTILIZATION";


    public InstanceMonitorServiceImpl(InstanceMonitorMapper instanceMonitorMapper, CmdbServiceManage cmdbServiceManage,
                                      ModuleIDManager moduleIDManager, ZabbixDubboService zabbixDubboService,MwSyncEngineCommonService mwSyncEngineCommonService) {
        this.instanceMonitorMapper = instanceMonitorMapper;
        this.cmdbServiceManage = cmdbServiceManage;
        this.moduleIDManager = moduleIDManager;
        this.mwSyncEngineCommonService = mwSyncEngineCommonService;
        this.zabbixDubboService = zabbixDubboService;
    }

    /**
     * 默认添加布局
     */
    public MwComponentLayoutInfo addDefaultOverViewTab(QueryMonitorParam param, List<MwTabLayoutInfo> layoutInfoList) throws Exception {
        MwComponentLayoutInfo mwComponentLayoutInfo = new MwComponentLayoutInfo();
        //生成默认tab标签数据
        List<MwLayoutLabelInfo> mwLayoutLabelInfos = createDefaultLabelInfos();
        mwComponentLayoutInfo.setLabels(mwLayoutLabelInfos);
        mwComponentLayoutInfo.setUserIdInfo();
        String templateName = param.getTemplateName();

        //资产新增时，默认为模板类型，用户对布局进行自定义修改后，再设置InstanceId
        mwComponentLayoutInfo.setTempName(templateName);
        //新增时，默认需要解析
        mwComponentLayoutInfo.setResolved(false);
        //添加概览空布局数据
        mwComponentLayoutInfo.setComponentLayout(layoutInfoList);
        doAdd(mwComponentLayoutInfo);
        return mwComponentLayoutInfo;
    }


    public MwComponentLayoutInfo getLayoutInfo(QueryMonitorParam param) throws Exception {
        String instanceId = param.getInstanceId();
        long time1 = System.currentTimeMillis();
        String templateName = param.getTemplateName();
        ComponentLayoutSearchParam layoutSearchParam = new ComponentLayoutSearchParam();
        MwComponentLayoutInfo layoutInfo = new MwComponentLayoutInfo();
        layoutSearchParam.setTemplateName(templateName);
        layoutSearchParam.setIgnoreDataAuth(true);
        //根据模板Id查询对应的布局数据
        List<MwComponentLayoutInfo> mwComponentLayoutInfos = doSelectList(layoutSearchParam);
        //对布局数据进行分析，有匹配的InstanceId的布局，优先使用，没有就用templateId的数据
        if (CollectionUtils.isNotEmpty(mwComponentLayoutInfos)) {
            //自定义实例布局数据
            MwComponentLayoutInfo instanceLayoutInfo = new MwComponentLayoutInfo();
            for (MwComponentLayoutInfo info : mwComponentLayoutInfos) {
                if (instanceId.equals(info.getAssetsId())) {//布局数据中有自定义的instanceId标识的数据
                    instanceLayoutInfo = info;
                }
            }
            //模版公用布局数据
            MwComponentLayoutInfo tempLayoutInfo = new MwComponentLayoutInfo();
            for (MwComponentLayoutInfo info : mwComponentLayoutInfos) {
                if (Strings.isNullOrEmpty(info.getAssetsId()) && !Strings.isNullOrEmpty(info.getTempName())) {//布局数据中有自定义的instanceId标识的数据
                    tempLayoutInfo = info;
                }
            }

            Map<String, MwTabLayoutInfo> tempLayoutInfoByTabId = tempLayoutInfo.getLayoutInfoByTabId();
            Map<String, MwTabLayoutInfo> instanceLayoutInfoByTabId = instanceLayoutInfo.getLayoutInfoByTabId();
            //使用自定义布局替换公用模板布局
            tempLayoutInfoByTabId.putAll(instanceLayoutInfoByTabId);
            List<MwTabLayoutInfo> collect = tempLayoutInfoByTabId.values().stream().collect(Collectors.toList());
            tempLayoutInfo.setComponentLayout(collect);
            layoutInfo = tempLayoutInfo;
        }
        if (layoutInfo == null || CollectionUtils.isEmpty(layoutInfo.getLabels())) {
            //空布局，创建概览tab页
            layoutInfo = addDefaultOverViewTab(param, getInitOverViewLayout(param));
        }
        if (!CollectionUtils.isEmpty(layoutInfo.getLabels())) {
            Set<String> collectId = layoutInfo.getLabels().stream().map(s -> s.getId()).collect(Collectors.toSet());
            Set<String> collectName = layoutInfo.getLabels().stream().map(s -> s.getName()).collect(Collectors.toSet());
            //默认固定的标签
            DefaultMonitorTabEnum[] values = DefaultMonitorTabEnum.values();
            List<String> path = param.getPath();
            for (int i = 0; i < values.length; i++) {
                //如果没有
                if (!collectId.contains(values[i].getId()) && !collectName.contains(values[i].getName())) {
                    List<String> groupId = values[i].getGroupId();
                    boolean containFlag = path.stream().anyMatch(groupId::contains);
                    boolean exclusiveFlag = path.stream().anyMatch(groupId::contains);
                    if(containFlag && !exclusiveFlag){
                        MwLayoutLabelInfo mwLayoutLabelInfo = new MwLayoutLabelInfo();
                        mwLayoutLabelInfo.setId(values[i].getId());
                        mwLayoutLabelInfo.setName(values[i].getName());
                        layoutInfo.getLabels().add(mwLayoutLabelInfo);
                    }
                }
            }
        }
        long time2 = System.currentTimeMillis();
        log.info("get getLayoutInfo 耗时::" + (time2 - time1) + "ms");
        return layoutInfo;
    }


    /**
     * 解析处理布局数据
     *
     * @param param
     * @return
     * @throws Exception
     */
    private MwComponentLayoutInfo resolvedComponentLayoutInfo(QueryMonitorParam param) throws Exception {
        String hostId = param.getHostId();
        int monitorServerId = param.getMonitorServerId();
        String instanceId = param.getInstanceId();
        MwComponentLayoutInfo layoutInfo = getLayoutInfo(param);
        //获取布局数据中所有需要重新解析的itemName
        Set<String> allItemNameSet = layoutInfo.getAllItemNameSet();
        Set<String> disItemNameSet = new HashSet<>();

        //item的id和name映射Map
        Map<String, Object> itemData = new HashMap<>();
        Map<String, Object> mapperData = new HashMap();
        LayoutItemMapperInfo layoutItemMapperInfo = new LayoutItemMapperInfo();
        if (CollectionUtils.isNotEmpty(allItemNameSet) && monitorServerId > 0 && !Strings.isNullOrEmpty(hostId)) {
            LayoutItemMapperServiceImpl itemMapperService = (LayoutItemMapperServiceImpl) cmdbServiceManage.getModelService(LayoutItemMapperServiceImpl.ID);
            //数据库查询
            LayoutItemMapperInfo itemMapperInfo = itemMapperService.doSelectById(instanceId);
            if (itemMapperInfo != null && itemMapperInfo.getMapperData() != null) {
                Map<String, Object> mapperDataBase = itemMapperInfo.getMapperData();
                for (String itemName : allItemNameSet) {
                    if (mapperDataBase.containsKey(itemName)) {
                        Object itemId = mapperDataBase.get(itemName);
                        itemData.put(itemName, itemId);
                    } else {
                        //数据库中未匹配的监控数据
                        disItemNameSet.add(itemName);
                    }
                }
            } else {
                disItemNameSet = allItemNameSet;
            }
            //对未匹配的数据进行监控查询，获取对应的itemId
            if (CollectionUtils.isNotEmpty(disItemNameSet)) {
                MWZabbixAPIResult resultItems = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.ITEMS_GET_SEARCH_BY_NAMES, monitorServerId, hostId, new ArrayList<>(disItemNameSet));
                if (resultItems != null && !resultItems.isFail()) {
                    List<MwZabbixItemResultParam> itemResult = JSONArray.parseArray(String.valueOf(resultItems.getData()), MwZabbixItemResultParam.class);
                    for (String itemNameStr : disItemNameSet) {
                        List<String> itemIds = new ArrayList<>();
                        for (MwZabbixItemResultParam node : itemResult) {
                            String itemId = node.getItemid();
                            ItemNameParam itemNameParam = itemNameFilterBracket(itemNameStr);
                            //没有分区接口
                            if (Strings.isNullOrEmpty(itemNameParam.getDevName())) {
                                ItemNameParam nodeParam = itemNameFilterBracket(node.getName());
                                String itemName = nodeParam.getItemName();
                                //截取对应的itemName匹配
                                if (itemName.equals(itemNameParam.getItemName())) {
                                    itemIds.add(itemId);
                                }
                            } else {//有分区接口 :[home]MW_DISK_UTILIZATION,使用全匹配
                                if (node.getName().equals(itemNameStr)) {
                                    itemIds.add(itemId);
                                }
                            }
                            if (node.getName().equals(itemNameStr)) {
                                itemIds.add(itemId);
                            }
                        }
                        itemData.put(itemNameStr, itemIds);
                    }
                } else {
                    log.info("未匹配的监控数据获取对应的itemId失败:" + disItemNameSet);
                }
            }
            //根据hostId、monitorServerId、itemNames,查询对应的itemId
            if (!CollectionUtils.isMapEmpty(itemData)) {
                //数据库中查询的数据
                if (itemMapperInfo != null && !CollectionUtils.isMapEmpty(itemMapperInfo.getMapperData())) {
                    mapperData = itemMapperInfo.getMapperData();
                }
                //将重新解析的查询数据，并入到数据库中，利用map的key不重复性，进行更新替换
                mapperData.putAll(itemData);
                layoutItemMapperInfo.setId(instanceId);
                layoutItemMapperInfo.setMapperData(mapperData);
                //itemId-name映射数据入库
                itemMapperService.doAdd(layoutItemMapperInfo);
            }
        }
        //将itemId数据回填
        layoutInfo.setAllItemIdByName(mapperData);
        if (layoutInfo != null && CollectionUtils.isNotEmpty(layoutInfo.getLabels())) {
            List<MwLayoutLabelInfo> mwLayoutLabelInfos = moveDefaultToEnd(layoutInfo.getLabels());
            layoutInfo.setLabels(mwLayoutLabelInfos);
        }
        return layoutInfo;
    }

    /**
     * 监控tab页排序概览排在第一，监控指标排在最后
     *
     * @param originalList
     * @return
     */
    public static List<MwLayoutLabelInfo> moveDefaultToEnd(List<MwLayoutLabelInfo> originalList) {
        List<MwLayoutLabelInfo> modifiedList = new ArrayList<>();
        MwLayoutLabelInfo defaultItem = null;
        MwLayoutLabelInfo overviewItem = null;
        for (MwLayoutLabelInfo item : originalList) {
            if (item.getId().equals(monitorTarget.getId())) {
                defaultItem = item;
            } else if (overview.equals(item.getName())) {
                overviewItem = item;
            } else {
                modifiedList.add(item);
            }
        }
        if (defaultItem != null) {
            modifiedList.add(defaultItem);
        }
        if (overviewItem != null) {
            modifiedList.add(0, overviewItem);
        }
        return modifiedList;
    }

    /**
     * 获取资产基础信息
     *
     * @param param
     * @return
     * @throws Exception
     */
    public MwInstanceBaseMonitorInfo getInstanceBaseInfo(QueryMonitorParam param) throws Exception {
        MwInstanceBaseMonitorInfo baseMonitorInfo = new MwInstanceBaseMonitorInfo();
        long time1 = System.currentTimeMillis();
        Map m = new HashMap();
        TableSearchParam tableSearchParam = new TableSearchParam();
        tableSearchParam.setInstanceId(param.getInstanceId());
        //通用实例字段
        tableSearchParam.setTableId(TableIdEnum.commonInstance.getCode());
        TableHeaderAndDataManage dataManage = SpringUtils.getBean(TableHeaderAndDataManage.class);
        List<Map> list = (List<Map>) dataManage.listTableData(tableSearchParam);
        long time2 = System.currentTimeMillis();
        if (CollectionUtils.isNotEmpty(list)) {
            m = list.get(0);
        }
        BeanUtil.copyProperties(m, baseMonitorInfo, CopyOptions.create().setIgnoreNullValue(true));

        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        //获取查询监控参数context
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        //获取查询监控processor
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param);
        HostDetailDto instanceBaseMonitorInfo = new HostDetailDto();
        if (processor != null) {
            instanceBaseMonitorInfo = processor.getUptimeAndCpuMemoryInfo(contextParam);
            if (instanceBaseMonitorInfo != null) {
                BeanUtil.copyProperties(instanceBaseMonitorInfo, baseMonitorInfo, CopyOptions.create().setIgnoreNullValue(true));
            }
        }
        //监控度，可用性，繁忙度获取
        InstanceMetricServiceImpl metricService = (InstanceMetricServiceImpl) cmdbServiceManage.getModelService(InstanceMetricServiceImpl.ID);
        InstanceMetricInfo algorithmByInstanceId = metricService.getAlgorithmByInstanceId(param.getInstanceId());
        if (algorithmByInstanceId != null) {
            baseMonitorInfo.setBusiness(algorithmByInstanceId.getBusynessValue());
            baseMonitorInfo.setHealthLevel(algorithmByInstanceId.getHealthinessValue());
            baseMonitorInfo.setUnused(algorithmByInstanceId.getAvailabilityValue());
        }

        long time3 = System.currentTimeMillis();
        log.info("dataManage.listTableData::" + (time2 - time1) + "ms;getUptimeAndCpuMemoryInfo::" + (time3 - time2) + "ms");
        return baseMonitorInfo;
    }

    /**
     * 获取资产可运行
     */
    public AvailableInfoDTO getAvailableInfo(MwMonitorHistoryParam param) {
        long time1 = 0l;
        long time2 = 0l;
        long time3 = 0l;
        QueryItemHistoryParam itemHistoryParam = historyParamConvert(param);
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        //获取查询监控参数context
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        //获取查询监控processor
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param);
        contextParam.setItemNameList(Arrays.asList(ZabbixItemEnum.MW_HOST_AVAILABLE.getItemName()));
        //查询资产可用性itemId
        List<MwZabbixItemResultParam> itemIdByName = processor.getItemIdByName(contextParam);
        if (CollectionUtils.isNotEmpty(itemIdByName)) {
            String itemid = itemIdByName.get(0).getItemid();
            String valueType = itemIdByName.get(0).getValue_type();
            itemHistoryParam.setItemIds(Arrays.asList(itemid));
            itemHistoryParam.setValueType(intValueConvert(valueType));
        }
        contextParam.setParam(itemHistoryParam);
        time1 = System.currentTimeMillis();

        //查询资产可用性历史数据
        List<MWItemHistoryDTO> availableByItemId = processor.getAvailableByItemId(contextParam);
        time2 = System.currentTimeMillis();

        List<MwHistoryDTO> historyDTOList = new ArrayList<>();
        AvailableInfoDTO infoDTO = new AvailableInfoDTO();
        List<AssetsAvailableDTO> colorData = new ArrayList<>();
        AssetsAvailableDTO availableDTO;
        long startTime = itemHistoryParam.getStartDate();
        int floor = 0;
        Long lastValue = -2L;
        int count = 0;
        Double sum = 0.0;
        int startIndex = 0;
        List<MWItemHistoryDTO> lastHisDTO = availableByItemId.stream().sorted(Comparator.comparing(s -> Long.valueOf(s.getClock()))).collect(Collectors.toList());
        for (int i = 0; i < lastHisDTO.size(); i++) {
            long lastVal = longValueConvert(lastHisDTO.get(i).getValue_avg());
            historyDTOList.add(MwHistoryDTO.builder()
                    .lastUpdateValue(getAvailableStatus(lastVal))
                    .value(width)
                    .dateTimeStr(lastHisDTO.get(i).getDateConvert()).build());
            if (lastVal == available1.getCode().longValue() || lastVal == available2.getCode().longValue()) {
                sum++;//为了计算可用率
            }
            if (lastValue != lastVal) {
                if ((count - 1) == 0) {
                    availableDTO = new AssetsAvailableDTO();
                    availableDTO.setGt(startIndex);
                    availableDTO.setLte(i);
                    availableDTO.setColor(getAvailableColor(lastValue));
                    colorData.add(availableDTO);
                    count--;
                }
                lastValue = lastVal;
                startIndex = i;
                count++;
            }
            if (i == lastHisDTO.size() - 1) {//最后收尾的值
                availableDTO = new AssetsAvailableDTO();
                availableDTO.setGt(startIndex);
                availableDTO.setLte(i);
                availableDTO.setColor(getAvailableColor(lastValue));
                colorData.add(availableDTO);
            }
            if (i == 0) {
                i = floor;
                for (int j = 0; j < floor; j++) {
                    startTime = startTime + 60;
                    historyDTOList.add(MwHistoryDTO.builder()
                            .lastUpdateValue(un_manage.getStatus())
                            .value(width)
                            .dateTimeStr(DateUtils.formatDateTime(new Date(startTime * 1000))).build());
                }
            }
        }
        time3 = System.currentTimeMillis();
        int size = lastHisDTO.size();
        if (size == 0) {
            infoDTO.setAvailablePer("0%");
        } else {
            String per = new BigDecimal(sum * 100 / size).setScale(2, BigDecimal.ROUND_HALF_UP).toString() + "%";
            infoDTO.setAvailablePer(per);
        }
        infoDTO.setColorData(colorData);
        infoDTO.setHistoryDTOList(historyDTOList);
        log.info("获取资产可用性总耗时：" + (time2 - time1) + "ms；" + (time3 - time2) + "ms；");
        return infoDTO;
    }

    /**
     * 获取布局数据的tab信息
     *
     * @return
     * @throws Exception
     */
    public List<MwLayoutLabelInfo> queryLayoutTabList(QueryMonitorParam param) throws Exception {
        resettingMonitorItemInfo(param);
        MwComponentLayoutInfo shareLayoutData = getLayoutInfo(param);
        List<MwLayoutLabelInfo> labels = shareLayoutData.getLabels();
        return labels;
    }

    /**
     * 获取布局数据的tab信息
     *
     * @param param
     * @return
     * @throws Exception
     */
    public MwTabLayoutInfo queryLayoutByTabId(MwTabLayoutInfo param) throws Exception {
        MwTabLayoutInfo mwTabLayoutInfo = new MwTabLayoutInfo();
        MwComponentLayoutInfo shareLayoutData = resolvedComponentLayoutInfo(param);
        Map<String, MwTabLayoutInfo> layoutInfoByTabId = shareLayoutData.getLayoutInfoByTabId();
        if (!CollectionUtils.isMapEmpty(layoutInfoByTabId) && layoutInfoByTabId.containsKey(param.getLabelId())) {
            mwTabLayoutInfo = layoutInfoByTabId.get(param.getLabelId());
        }
        return mwTabLayoutInfo;
    }

    /**
     * 初始化监控数据查询参数
     *
     * @param instanceId
     * @return
     * @throws Exception
     */
    public QueryMonitorParam initMonitorParam(String instanceId) throws Exception {
        QueryMonitorParam param = new QueryMonitorParam();
        long time1 = System.currentTimeMillis();
        if (!Strings.isNullOrEmpty(instanceId)) {
            InstanceServiceImpl modelService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceInfo instanceParam = new InstanceInfo();
            instanceParam.setId(instanceId);
            InstanceInfo instanceInfo = modelService.doSelectById(instanceParam);
            if (instanceInfo != null) {
                //获取基础监控数据
                param.setMonitorServerId(instanceInfo.getMonitorServerId());
                param.setMonitorType(instanceInfo.getMonitorType());
                param.setTemplateName(instanceInfo.getTemplateName());
                //数据源id有值，且监控id为空，需要通过同步数据源获取对应的监控信息
                String engineId = strValueConvert(instanceInfo.getEngineIdeKey());
                log.info("initMonitorParam::engineId"+engineId+";instanceInfo::"+instanceInfo);
                if(!Strings.isNullOrEmpty(engineId) && intValueConvert(instanceInfo.getMonitorServerId())==0 ){
                    List<MwSyncEngineDto> allMwSyncEngine = mwSyncEngineCommonService.getAllMwSyncEngine();

                    Map<String, MwSyncEngineDto> collect = allMwSyncEngine.stream().collect(Collectors.toMap(s -> strValueConvert(s.getId()), s -> s));
                    log.info("initMonitorParam::collect"+collect);
                    if(collect!=null && collect.containsKey(engineId)){
                        MwSyncEngineDto engineDto = collect.get(engineId);
                        log.info("initMonitorParam::engineDto"+engineDto.toString());
                        Integer monitorEngineId = intValueConvert(engineDto.getMonitorEngineId());
                        if(CollectionUtils.isNotEmpty(engineDto.getEnginePathList())){
                            String monitorType = engineDto.getEnginePathList().get(0);
                            param.setMonitorType(monitorType);
                        }
                        param.setMonitorServerId(monitorEngineId);
                        log.info("initMonitorParam::monitorEngineId"+monitorEngineId);
                    }
                }
                param.setInstanceId(instanceId);
                param.setModelId(instanceInfo.getModelId());
                param.setInstanceName(instanceInfo.getInstanceName());
                param.setMwEngineSource(strValueConvert(instanceInfo.getEngineSourceKey()));
                param.setHostId(instanceInfo.getMonitorTypeId());
                param.setTemplateId(instanceInfo.getHostTemplateId());
                param.setTemplateName(instanceInfo.getTemplateName());
                param.setTemplateIds(Arrays.asList(instanceInfo.getHostTemplateId()));
                param.setUsers(instanceInfo.getUsers());
                param.setGroups(instanceInfo.getGroups());
                param.setOrgs(instanceInfo.getOrgs());
                param.setPath(instanceInfo.getPath());
            }
            MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
            MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
            contextParam.setQueryMonitorParam(param);
            MonitorProcessor processor = processorConvert.getMonitorProcessor(param);

            //查询监控资产的所有模板id
            if (processor != null) {
                long time11 = System.currentTimeMillis();
                Map<String, List> resultListMap = handleMethodWithTimeout(timeOutNum, TimeUnit.SECONDS, processor, contextParam);
                long time12 = System.currentTimeMillis();
                if (resultListMap != null && resultListMap.size() > 0) {
                    List<MwKeyValueParam> allTemplateInfoList = resultListMap.get(allTemplateInfoKey);
                    List<String> discoveryIdsList = resultListMap.get(discoveryIdsKey);
                    if (CollectionUtils.isNotEmpty(allTemplateInfoList)) {
                        List<String> collect = allTemplateInfoList.stream().map(s -> s.getValue()).collect(Collectors.toList());
                        param.setTemplateIds(collect);
                        if (Strings.isNullOrEmpty(param.getTemplateId()) || "0".equals(param.getTemplateId())) {
                            param.setTemplateId(allTemplateInfoList.get(0).getValue());
                        }
                        String zabbixTempName = allTemplateInfoList.get(0).getName();
                        if(Strings.isNullOrEmpty(param.getTemplateName()) && !Strings.isNullOrEmpty(zabbixTempName)){
                            Map ms = new HashMap();
                            ms.put(idKey,instanceInfo.getId());
                            ms.put(mw_templateName,zabbixTempName);
                            modelService.batchUpdateByInstanceMap(Arrays.asList(ms));
                        }
                        param.setTemplateName(allTemplateInfoList.get(0).getName());
                    }
                    if (CollectionUtils.isNotEmpty(discoveryIdsList)) {
                        param.setDiscoveryIds(discoveryIdsList);
                    }
                }
                log.info("resultListMapInfos" + resultListMap + ";getResultListMapTime::" + (time12 - time11));
            }
        }
        long time2 = System.currentTimeMillis();
        log.info("get initMonitorParam time::" + (time2 - time1) + "ms");
        return param;
    }


    public Map<String, List> handleMethodWithTimeout(long timeout, TimeUnit timeUnit, MonitorProcessor processor, MonitorParamContext contextParam) throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(2);
        // 提交两个任务并行执行
        Future<List<MwKeyValueParam>> future1 = executor.submit(() -> processor.getAllTemplateInfoByHostId(contextParam));
        Future<List<String>> future2 = executor.submit(() -> processor.getDiscoveryIdByHostId(contextParam));
        Map<String, List> maps = new HashMap<>();
        try {
            // 等待两个任务的结果，超时时间统一设为5秒
            List<MwKeyValueParam> result1 = future1.get(timeout, timeUnit);
            List<String> result2 = future2.get(timeout, timeUnit);
            maps.put(allTemplateInfoKey, result1);
            maps.put(discoveryIdsKey, result2);
            return maps; // 合并两个结果
        } catch (TimeoutException e) {
            // 取消任务并返回默认值
            future1.cancel(true);
            future2.cancel(true);
            return maps;
        } catch (ExecutionException e) {
            throw new RuntimeException("Error occurred while fetching names", e);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return maps;
        } finally {
            executor.shutdown();
            return maps;
        }
    }


    /**
     * 获取监控下拉数据
     *
     * @param param
     * @return
     * @throws Exception
     */
    public List<ItemApplication> queryItemInfoList(QueryArgumentsParam param) throws Exception {
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        //获取查询监控参数context
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        //获取查询监控processor
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param);
        List<ItemApplication> itemInfoList = new ArrayList<>();
        if (processor != null) {
            itemInfoList = processor.getItemInfoList(contextParam);
        }
        return itemInfoList;
    }

    /**
     * 高级表格查询所有应用集list
     *
     * @param param
     * @return
     * @throws Exception
     */
    public List<MwZabbixApplicationResultParam> getApplicationList(QueryMonitorParam param) throws Exception {
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        //获取查询监控参数context
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        //获取查询监控processor
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param);
        List<MwZabbixApplicationResultParam> list = new ArrayList<>();
        if (processor != null) {
            List<ApplicationDTO> application = processor.getApplication(contextParam);
            list = JSONArray.parseArray(JSONArray.toJSONString(application), MwZabbixApplicationResultParam.class);
        }
        return list;
    }

    /**
     * 高级表格根据应用集查询监控项和监控设备list
     *
     * @param param
     * @return
     * @throws Exception
     */
    public AdvanceTableItemParam getItemListByApplication(MwZabbixApplicationResultParam param) throws Exception {
        //获取监控项List 和监控设备list
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        //获取查询监控参数context
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        //获取查询监控processor
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param);
        List<MwZabbixItemResultParam> list = new ArrayList<>();
        Map<String, String> itemNameMap = new HashMap<>();
        if (processor != null) {
            MWZabbixAPIResult result = processor.getItemNameByAppName(contextParam);
            list = JSONArray.parseArray(String.valueOf(result.getData()), MwZabbixItemResultParam.class);
            Set<String> itemNames = new HashSet<>();
            for (MwZabbixItemResultParam itemResult : list) {
                String name = itemResult.getName();
                itemNames.add(name);
            }
            //item映射中文名称
            itemNameMap = getItemNameMap(itemNames, processor);

        }
        Set<String> strNameSet = new HashSet();
        Set<String> devNameSet = new HashSet();
        AdvanceTableItemParam tableItemParam = new AdvanceTableItemParam();
        List<MonitorItemInfoMappingParam> newItemList = new ArrayList<>();
        List<String> strNameList = new ArrayList<>();
        List<MonitorItemInfoMappingParam> oldItemList = new ArrayList<>();
        List<String> oldNameAllList = new ArrayList<>();
        List<String> oldDevList = new ArrayList<>();
        List<String> devNameList = new ArrayList<>();

        for (MwZabbixItemResultParam itemResult : list) {
            String name = itemResult.getName();
            //例: [2C C5 D3 3B 6D 00 ,BLUEMOON-WIFI]<10.3.48.154>MW_CLIENTS_CHANNELS
            //[2C C5 D3 3B 6D 00 ,BLUEMOON-WIFI]<10.3.48.154>为监控设备名称   MW_CLIENTS_CHANNELS监控项名称
            String itemName = name; //监控项名称
            MonitorItemInfoMappingParam mapOldName = new MonitorItemInfoMappingParam();
            if (itemNameMap != null) {
                ItemNameParam itemNameParam = itemNameFilterBracket(name);
                String chItemName = itemNameMap.get(itemNameParam.getItemName());
                if (Strings.isNullOrEmpty(chItemName)) {
                    chItemName = itemName;
                }
                mapOldName.setChName(itemNameParam.getDevName() + chItemName);
                mapOldName.setName(itemName);
            }
            oldItemList.add(mapOldName);
            String devName = ""; //监控设备名称
            //监控项名称截取,包含括号
            ItemNameParam itemNameParam = itemNameFilterBracket(name);
            devName = itemNameParam.getDevName();
            itemName = itemNameParam.getItemName();
            if (!Strings.isNullOrEmpty(devName)) {
                oldNameAllList.add(devName);
            }
            if (!strNameSet.contains(itemName)) {
                MonitorItemInfoMappingParam newName = new MonitorItemInfoMappingParam();
                String chItemName = itemNameMap.get(itemName);
                strNameList.add(itemName);
                if (Strings.isNullOrEmpty(chItemName)) {
                    chItemName = itemName;
                }
                newName.setChName(chItemName);
                newName.setName(itemName);
                newItemList.add(newName);
            }
            if (!devNameSet.contains(devName) && !Strings.isNullOrEmpty(devName)) {
                devNameList.add(devName);
            }
            strNameSet.add(itemName);
            if (!Strings.isNullOrEmpty(devName)) {
                devNameSet.add(devName);
            }
        }
        if (devNameList != null && devNameList.size() != 0) {
            Collections.sort(devNameList, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
                }
            });
        }
        //高级表格监控项分为监控名称和监控设备，当前应用集下的所有item指标都能分为对应的监控项名称和监控先设备时，
        //则itemName和devName都有值，否则不截取
        if (oldNameAllList.size() != list.size()) {
            tableItemParam.setItemNameList(oldItemList);
            tableItemParam.setDevNameList(oldDevList);
        } else {
            tableItemParam.setItemNameList(newItemList);
            tableItemParam.setDevNameList(devNameList);
        }
        return tableItemParam;
    }

    @Override
    public MwComponentLayoutInfo genObject() {
        return new MwComponentLayoutInfo();
    }

    @Override
    Object doAdd(MwComponentLayoutInfo param) throws Exception {
        instanceMonitorMapper.insert(param);
        return true;
    }


    /**
     * 保存布局数据
     *
     * @param layoutInfo
     * @throws Exception
     */
    public void addLayoutDataTabTest(MwTabLayoutInfo layoutInfo) throws Exception {
        //是否默认布局，默认布局：同模板的资产共同使用，自定义布局：仅此资产使用
        if (layoutInfo.isDefaultFlag()) {
            //新增修改之后，是否解析标识设为false，需要重新解析
            layoutInfo.setResolved(false);
            MwComponentLayoutInfo layoutData = resolvedComponentLayoutInfo(layoutInfo);
            List<MwTabLayoutInfo> componentLayout = layoutData.getComponentLayout();
            if (componentLayout != null) {
                boolean isAdd = true;
                for (MwTabLayoutInfo mwTabLayoutInfo : componentLayout) {
                    if (layoutInfo.getLabelId().equals(mwTabLayoutInfo.getLabelId())) {
                        //有匹配的，替换
                        layoutInfo.setLayout(layoutInfo.getLayout());
                        BeanUtil.copyProperties(layoutInfo, mwTabLayoutInfo, CopyOptions.create().setIgnoreNullValue(true));
                        isAdd = false;
                    }
                }
                if (isAdd) {
                    componentLayout.add(layoutInfo);
                }
            }
            doUpdate(layoutData);
        } else {
            ComponentLayoutSearchParam layoutSearchParam = new ComponentLayoutSearchParam();
            layoutSearchParam.setTemplateName(layoutInfo.getTemplateName());
            layoutSearchParam.setInstanceId(layoutInfo.getInstanceId());
            layoutSearchParam.setIgnoreDataAuth(true);
            List<MwComponentLayoutInfo> mwComponentLayoutInfos = doSelectList(layoutSearchParam);
            //先判断自定义布局是否存在，存在就更新，不存在则新增
            if (CollectionUtils.isNotEmpty(mwComponentLayoutInfos)) {
                //更新
                MwComponentLayoutInfo componentLayoutInfo = mwComponentLayoutInfos.get(0);
                Map<String, MwTabLayoutInfo> layoutInfoByTabId = componentLayoutInfo.getLayoutInfoByTabId();
                layoutInfoByTabId.put(layoutInfo.getLabelId(), layoutInfo);
                List<MwTabLayoutInfo> list = layoutInfoByTabId.values().stream().toList();
                componentLayoutInfo.setComponentLayout(list);
                doUpdate(componentLayoutInfo);
            } else {
                //新增
                MwComponentLayoutInfo mwComponentLayoutInfo = new MwComponentLayoutInfo();
                mwComponentLayoutInfo.setLabels(new ArrayList<>());
                mwComponentLayoutInfo.setUserIdInfo();
                String templateName = layoutInfo.getTemplateName();
                //templateName
                String instanceId = layoutInfo.getInstanceId();
                //资产新增时，默认为模板类型，
                mwComponentLayoutInfo.setTempName(templateName);
                //用户对布局进行自定义修改后，再设置InstanceId
                mwComponentLayoutInfo.setAssetsId(instanceId);
                //新增时，默认需要解析
                mwComponentLayoutInfo.setResolved(true);
                //添加概览空布局数据
                mwComponentLayoutInfo.setComponentLayout(Arrays.asList(layoutInfo));
                doAdd(mwComponentLayoutInfo);
            }
        }
    }


    public void addLayoutDataTab(MwTabLayoutInfo layoutInfo) throws Exception {
        //新增修改之后，是否解析标识设为false，需要重新解析
        layoutInfo.setResolved(false);
        MwComponentLayoutInfo layoutData = resolvedComponentLayoutInfo(layoutInfo);
        List<MwTabLayoutInfo> componentLayout = layoutData.getComponentLayout();
        if (componentLayout != null) {
            boolean isAdd = true;
            for (MwTabLayoutInfo mwTabLayoutInfo : componentLayout) {
                if (layoutInfo.getLabelId().equals(mwTabLayoutInfo.getLabelId())) {
                    //有匹配的，替换
                    layoutInfo.setLayout(layoutInfo.getLayout());
                    BeanUtil.copyProperties(layoutInfo, mwTabLayoutInfo, CopyOptions.create().setIgnoreNullValue(true));
                    isAdd = false;
                }
            }
            if (isAdd) {
                componentLayout.add(layoutInfo);
            }
        }
        doUpdate(layoutData);
    }

    /**
     * 获取固定的标签信息
     *
     * @throws Exception
     */
    public List<MwLayoutLabelInfo> getDefaultTabInfo() throws Exception {
        List<MwLayoutLabelInfo> list = new ArrayList<>();
        for (DefaultMonitorTabEnum tabEnum : DefaultMonitorTabEnum.values()) {
            MwLayoutLabelInfo mwInfo = new MwLayoutLabelInfo();
            mwInfo.setId(tabEnum.getId());
            mwInfo.setName(tabEnum.getName());
            list.add(mwInfo);
        }
        return list;
    }


    /**
     * 新增tab标签信息
     *
     * @param mwLayoutLabelInfo
     * @throws Exception
     */
    public void addTabInfo(MwLayoutLabelInfo mwLayoutLabelInfo) throws Exception {
        if (mwLayoutLabelInfo == null) {
            return;
        }
        MwComponentLayoutInfo layoutData = resolvedComponentLayoutInfo(mwLayoutLabelInfo);
        //name不存在，ids存在，表示前端选择的是固定标签页
        if (CollectionUtils.isNotEmpty(mwLayoutLabelInfo.getIds()) && Strings.isNullOrEmpty(mwLayoutLabelInfo.getName())) {
            List<MwLayoutLabelInfo> list = new ArrayList<>();
            for (String id : mwLayoutLabelInfo.getIds()) {
                MwLayoutLabelInfo labelInfo = new MwLayoutLabelInfo();
                labelInfo.setId(id);
                labelInfo.setName(DefaultMonitorTabEnum.getDefaultMonitorTab(id).getName());
                list.add(labelInfo);
            }
            layoutData.getLabels().addAll(list);
        }
        //自定义输入tab信息
        if (!Strings.isNullOrEmpty(mwLayoutLabelInfo.getName())) {
            createLabelInfo(mwLayoutLabelInfo);
            layoutData.getLabels().add(mwLayoutLabelInfo);
        }
        List<MwLayoutLabelInfo> collect = layoutData.getLabels().stream().distinct().collect(Collectors.toList());
        //排序
        List<MwLayoutLabelInfo> mwLayoutLabelInfos = moveDefaultToEnd(collect);
        layoutData.setLabels(mwLayoutLabelInfos);
        doUpdate(layoutData);
    }

    /**
     * 修改tab标签信息
     *
     * @param mwLayoutLabelInfo
     * @throws Exception
     */
    public void updateTabInfo(MwLayoutLabelInfo mwLayoutLabelInfo) throws Exception {
        MwComponentLayoutInfo layoutData = resolvedComponentLayoutInfo(mwLayoutLabelInfo);
        List<MwLayoutLabelInfo> labels = layoutData.getLabels();
        for (MwLayoutLabelInfo labelInfo : labels) {
            if (labelInfo != null && labelInfo.getId().equals(mwLayoutLabelInfo.getId())) {
                labelInfo.setName(mwLayoutLabelInfo.getName());
            }
        }
        doUpdate(layoutData);
    }

    /**
     * 删除tab标签信息
     *
     * @param mwLayoutLabelInfo
     * @throws Exception
     */
    public void deleteTabInfo(MwLayoutLabelInfo mwLayoutLabelInfo) throws Exception {
        MwComponentLayoutInfo layoutData = resolvedComponentLayoutInfo(mwLayoutLabelInfo);
        List<MwTabLayoutInfo> layoutInfos = layoutData.getComponentLayout();
        //删除layoutInfo布局数据
        Iterator<MwTabLayoutInfo> layoutInfoIterator = layoutInfos.iterator();
        while (layoutInfoIterator.hasNext()) {
            MwTabLayoutInfo next = layoutInfoIterator.next();
            if (CollectionUtils.isNotEmpty(mwLayoutLabelInfo.getConvertIds()) && mwLayoutLabelInfo.getConvertIds().contains(next.getLabelId())) {
                layoutInfoIterator.remove();
            }
        }
        //删除labelInfo标签数据
        List<MwLayoutLabelInfo> labels = layoutData.getLabels();
        Iterator<MwLayoutLabelInfo> iterator = labels.iterator();
        while (iterator.hasNext()) {
            MwLayoutLabelInfo next = iterator.next();
            if (CollectionUtils.isNotEmpty(mwLayoutLabelInfo.getConvertIds()) && mwLayoutLabelInfo.getConvertIds().contains(next.getId())) {
                iterator.remove();
            }
        }
        doUpdate(layoutData);
    }


    @Override
    boolean doUpdate(MwComponentLayoutInfo param) throws Exception {
        Query query = new Query(CriteriaWrapper.where(MwComponentLayoutInfo::getId).is(param.getId()));
        Update update = CMDBTool.genMongoUpdate(param, null, null);
        CMDBTool.updateFirst(instanceMonitorMapper, query, update);
        return true;
    }

    @Override
    boolean doRemove(MwComponentLayoutInfo param) throws Exception {
        return false;
    }

    @Override
    Object doBatchAdd(Object params) throws Exception {
        if (params != null && params instanceof List) {
            List<MwComponentLayoutInfo> paramsList = (List<MwComponentLayoutInfo>) params;
            instanceMonitorMapper.insertAll(paramsList);
        }
        return true;
    }

    @Override
    boolean doBatchUpdate(Object params) {
        return false;
    }

    private void batchUpdateLayout(List<MwComponentLayoutInfo> list) throws Exception {
        if(CollectionUtils.isNotEmpty(list)){
            List<Pair<Query, Update>> updateList = new ArrayList<>();
            //UNORDERED是异步执行，有错误跳过继续执行；ORDERED时有序执行，遇到错误终止
            BulkOperations operations = instanceMonitorMapper.bulkOps(BulkOperations.BulkMode.UNORDERED, MwComponentLayoutInfo.class);
            for (MwComponentLayoutInfo data : list) {
                // 添加查询条件
                Query query = new Query(CriteriaWrapper.where(MwComponentLayoutInfo::getId).is(data.getId()));
                Update update = CMDBTool.genMongoUpdate(data, null, null);
                Pair<Query, Update> updatePair = Pair.of(query, update);
                updateList.add(updatePair);
            }
            operations.updateMulti(updateList);
            operations.execute();
        }
    }

    @Override
    MwComponentLayoutInfo doSelectById(Object id) throws Exception {
        return null;
    }

    @Override
    List<MwComponentLayoutInfo> doSelectList(Object param) throws Exception {
        ComponentLayoutSearchParam layoutSearchParam = (ComponentLayoutSearchParam) param;
        layoutSearchParam.convert();
        Criteria criteria = genCriteria(layoutSearchParam);
        List<MwComponentLayoutInfo> ret = CMDBTool.selectAuthorizedList(MwComponentLayoutInfo.class, instanceMonitorMapper, criteria, layoutSearchParam);
        return ret;
    }

    @Override
    boolean doBatchRemove(Object params) throws Exception {
        if (params instanceof List) {
            List<String> listIds = (List<String>) params;
            if(CollectionUtils.isNotEmpty(listIds)){
                Query query = new Query(CriteriaWrapper.where(MwComponentLayoutInfo::getId).in(listIds));
                instanceMonitorMapper.remove(query);
            }
        }
        return true;
    }

    /**
     * 创建默认布局tab标签信息
     */
    private List<MwLayoutLabelInfo> createDefaultLabelInfos() {
        List<MwLayoutLabelInfo> mwLayoutLabelInfos = new ArrayList<>();
        for (DefaultMonitorTabEnum defaultTab : DefaultMonitorTabEnum.values()) {
            MwLayoutLabelInfo mwLayoutLabelInfo = new MwLayoutLabelInfo();
            mwLayoutLabelInfo.setName(defaultTab.getName());
            mwLayoutLabelInfo.setId(defaultTab.getId());
            mwLayoutLabelInfos.add(mwLayoutLabelInfo);
        }
        return mwLayoutLabelInfos;
    }

    /**
     * 创建布局tab标签信息
     */
    private void createLabelInfo(MwLayoutLabelInfo mwLayoutLabelInfo) {
        if (Strings.isNullOrEmpty(mwLayoutLabelInfo.getName())) {
            mwLayoutLabelInfo.setName(overView);
        }
        mwLayoutLabelInfo.setId(moduleIDManager.getIDStr(IDModelType.Model));
    }

    public MwComponentLayoutInfo getShareLayoutData() {
        return shareLayoutData;
    }

    public void setShareLayoutData(MwComponentLayoutInfo shareLayoutData) {
        this.shareLayoutData = shareLayoutData;
    }


    /**
     * 获取历史数据
     *
     * @param param
     * @return
     */
    public Object getMonitorHistoryInfo(MwMonitorHistoryParam param) throws Exception {
        String chartType = param.getChartType();
        ChartTypeEnum chartEnum = ChartTypeEnum.getChartEnumByName(chartType);
        String trendType = chartEnum.getQueryType();
        //判断是否取趋势数据
        if (!Strings.isNullOrEmpty(param.getTrendType())) {
            trendType = param.getTrendType();
        }
        HistoryHandlerProcessor processor = MonitorHistoryHandlerFactory.build(trendType, cmdbServiceManage, zabbixDubboService);
        Object o = processor.genMonitorData(param);
        return o;
    }

    public Object getAllApplicationList(QueryMonitorParam param) {
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        MonitorParamContext contextParam = processorConvert.getContextParam();
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param.getInstanceId());
        List<String> hostIds = new ArrayList<>();
        List<ApplicationDTO> allApplicationList = new ArrayList<>();
        if (processor != null) {
            //判断该实例是否属于Vcenter
            InstanceInfo instanceInfo = (InstanceInfo) processor.getMonitorValue();
            String modelId = instanceInfo.getModelId();
            CustomModelServiceImpl modelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
            ModelInfo modelInfo = modelService.doSelectById(modelId);
            VirtualizationTypeEnum virtualizationType = getVirtualizationType(modelInfo.getSpec());
            //获取虚拟化Vcenter关联设备的监控主机id
            if (virtualizationType != null && virtualizationType.equals(VCENTER)) {
                String inBandIp = instanceInfo.getInBandIp();
                contextParam.setParam(inBandIp);
                hostIds = processor.getVcenterRelationAssetsHostId(contextParam);
            }
            //获取监控指标的应用集列表
            param.setHostIds(hostIds);
            contextParam.setQueryMonitorParam(param);
            allApplicationList = processor.getAllApplicationList(contextParam);
        }
        return allApplicationList;
    }

    /**
     * 监控指标根据应用集名称获取指标数据
     *
     * @param param
     * @return
     * @throws Exception
     */
    public Object getItemInfoByApplication(MwQueryApplicationParam param) throws Exception {
        boolean isQueryAll = false;
        if (ZabbixItemConstant.APPLICATION_NAME.equals(param.getApplicationName())) {
            param.setApplicationName(null);
            isQueryAll = true;
        }
        boolean isQueryLLD = false;
        if (ZabbixItemConstant.APPLICATION_LLD.equals(param.getApplicationName())) {
            isQueryLLD = true;
        }
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param.getInstanceId());
        List<String> hostIds = new ArrayList<>();
        List<MwMonitorItemParam> list = new ArrayList<>();
        if (!isQueryLLD) {
            if (param.getCount() != null && param.getCount() > 2000) {
                //应用集下的监控项大于2000，则进行分批次查询
                //第一步，先获取该应用集下的所有itemIds，
                List<String> itemIdsByAppName = processor.getItemIdsByAppName(contextParam);
                List<List<String>> partition = Lists.partition(itemIdsByAppName, 1500);
                for (List<String> listIds : partition) {
                    param.setItemIds(listIds);
                    contextParam.setParam(param);
                    MWZabbixAPIResult result = processor.getItemInfoByAppNameAndIds(contextParam);
                    List<MwMonitorItemParam> resultParams = JSONArray.parseArray(String.valueOf(result.getData()), MwMonitorItemParam.class);
                    list.addAll(resultParams);
                }
            } else {
                //直接根据应用集名称查询item信息
                MWZabbixAPIResult result = processor.getItemInfoByAppName(contextParam);
                if (result != null) {
                    list = JSONArray.parseArray(String.valueOf(result.getData()), MwMonitorItemParam.class);
                }
            }
        }
        //查询全部的，包含LLD的指标
        if (isQueryAll || isQueryLLD) {
            //直接根据应用集名称查询item信息
            MWZabbixAPIResult result = processor.getDRuleByHostId(contextParam);
            if (result != null) {
                list.addAll(JSONArray.parseArray(String.valueOf(result.getData()), MwMonitorItemParam.class));
            }
        }
        contextParam.setQueryMonitorParam(param);
        getLastValueConvert(processor, list, contextParam);
        String queryStatus;
        //状态过滤
        if (Strings.isNullOrEmpty(param.getStatus())) {
            queryStatus = normal;
        } else {
            queryStatus = param.getStatus();
        }
        List<MwMonitorItemParam> filterStatusList = list.stream().filter(e -> e.getState().equals(queryStatus)).collect(Collectors.toList());
        //查询搜索
        List<MwMonitorItemParam> collect = filterStatusList;
        if (!Strings.isNullOrEmpty(param.getQueryValue())) {
            collect = filterStatusList.stream().filter(s -> (!Strings.isNullOrEmpty(s.getChName()) ? s.getChName().toLowerCase().contains(param.getQueryValue().toLowerCase()) : s.getName().toLowerCase().contains(param.getQueryValue().toLowerCase()))
                    || (!Strings.isNullOrEmpty(s.getState()) && s.getState().toLowerCase().contains(param.getQueryValue().toLowerCase()))
                    || (!Strings.isNullOrEmpty(strValueConvert(s.getLastvalue())) && strValueConvert(s.getLastvalue()).toLowerCase().contains(param.getQueryValue().toLowerCase()))
                    || (!Strings.isNullOrEmpty(s.getLastclock()) && s.getLastclock().toLowerCase().contains(param.getQueryValue().toLowerCase()))
                    || (!Strings.isNullOrEmpty(s.getDelay()) && s.getDelay().toLowerCase().contains(param.getQueryValue().toLowerCase()))).collect(Collectors.toList());

        }
        //排序
        if (!Strings.isNullOrEmpty(param.getSortName())) {
            ListSortUtil<MwMonitorItemParam> listSortUtil = new ListSortUtil<>();
            String sort = "sort" + param.getSortName().substring(0, 1).toUpperCase() + param.getSortName().substring(1);
            //查看当前属性名称是否在对象中
            try {
                Field field = MwMonitorItemParam.class.getDeclaredField(param.getSortName());
                listSortUtil.sort(collect, param.getSortName(), param.getSortOrder());
            } catch (NoSuchFieldException e) {
                log.info("has no field", e);
                listSortUtil.sort(collect, sort, param.getSortOrder());
            }
        }
        MWPage customPageInfo = getCustomPageInfo(param, collect);
        return customPageInfo;
    }

    public boolean itemCheckNow(QueryMonitorParam param) {
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param.getInstanceId());
        boolean b = false;
        if (processor != null) {
            b = processor.itemCheckNow(contextParam);
        }
        return b;
    }

    public List<MwCommonItemInfo> queryItemInfos(QueryItemInfoListParam param) throws Exception {
        List<MwMonitorItemParam> lists = new ArrayList<>();
        List<MwCommonItemInfo> list = new ArrayList<>();
        MwMonitorProcessorConvert processorConvert = new MwMonitorProcessorConvert(cmdbServiceManage, zabbixDubboService);
        MonitorParamContext contextParam = processorConvert.getContextParam(param, null);
        MonitorProcessor processor = processorConvert.getMonitorProcessor(param.getInstanceId());
        if (processor != null) {
            MWZabbixAPIResult result = processor.queryItemInfos(contextParam);
            if (result != null && result.getCode() == 0) {
                lists = JSONArray.parseArray(JSON.toJSONString(result.getData()), MwMonitorItemParam.class);
            }
            contextParam.setQueryMonitorParam(param);
            getLastValueConvert(processor, lists, contextParam);
            list = BeanUtil.copyToList(lists, MwCommonItemInfo.class, CopyOptions.create().setIgnoreNullValue(true));
        }
        return list;
    }


    /**
     * @param names
     * @param processor
     * @return
     * @throws Exception
     */
    public static Map<String, String> getItemNameMap(Set<String> names, MonitorProcessor processor) throws Exception {
        Set<String> itemNames = new HashSet<>();
        Map<String, String> itemNameMap = new HashMap<>();
        for (String name : names) {
            //监控项名称截取
            ItemNameParam itemNameParam = itemNameFilter(name);
            itemNames.add(itemNameParam.getItemName());
        }
        ItemNameMapperInfo itemNameMapperInfo = new ItemNameMapperInfo();
        itemNameMapperInfo.setItemList(new ArrayList<>(itemNames));
        if (processor != null) {
            List<ItemNameMapperInfo> itemNameMapperList = processor.getItemNameMapperList(itemNameMapperInfo);
            //item映射中文名称
            itemNameMap = itemNameMapperList.stream().filter(s -> !Strings.isNullOrEmpty(s.getItem())).collect(Collectors.toMap(s -> s.getItem(), s -> s.getDescrCn(), (o1, o2) -> o1));
        }
        return itemNameMap;
    }


    public static Map<String, Map> getValueMapIdInfo(Set<String> valuemapIds, MonitorProcessor processor, MonitorParamContext contextParam) {
        Map<String, Map> valuemapidMap = new HashMap<>();
        contextParam.setParam(new ArrayList<>(valuemapIds));
        List<ValuemapDto> valueMapByIdList = processor.getValueMapByIdList(contextParam);
        for (ValuemapDto dto : valueMapByIdList) {
            Map map1 = new HashMap();
            for (ValueMappingDto val : dto.getMappings()) {
                map1.put(val.getValue(), val.getNewvalue());
            }
            //映射数据转为map格式
            valuemapidMap.put(dto.getValuemapid(), map1);
        }
        return valuemapidMap;
    }

    public void getLastValueConvert(MonitorProcessor processor, List<MwMonitorItemParam> lists, MonitorParamContext contextParam) throws Exception {
        Set<String> itemNames = new HashSet<>();
        Set<String> valuemapIds = new HashSet<>();
        for (MwMonitorItemParam itemResult : lists) {
            String name = itemResult.getName();
            if (!Strings.isNullOrEmpty(itemResult.getValuemapid())) {
                valuemapIds.add(itemResult.getValuemapid());
            }
            if (!Strings.isNullOrEmpty(name)) {
                itemNames.add(name);
            }
        }
        //item映射中文名称
        Map<String, String> itemNameMap = getItemNameMap(itemNames, processor);
        Map<String, Map> valuemapidMap = getValueMapIdInfo(valuemapIds, processor, contextParam);
        for (MwMonitorItemParam zabbixItemResultParam : lists) {
            String name = zabbixItemResultParam.getName();
            ItemNameParam itemNameParam = itemNameFilterBracket(name);
            String itemName = itemNameParam.getItemName();
            String devName = itemNameParam.getDevName();
            if (itemNameMap != null && itemNameMap.containsKey(itemName)) {
                String chItemName = itemNameMap.get(itemName);
                zabbixItemResultParam.setChName(devName + chItemName);
            }
            //设置值类型
            zabbixItemResultParam.initParamConvert();
            String lastValue = strValueConvert(zabbixItemResultParam.getLastvalue());
            String valuemapid = zabbixItemResultParam.getValuemapid();
            UnitResult unitResult = valueConvertUnit(zabbixItemResultParam.getUnits(), lastValue, valuemapid, valuemapidMap);
            zabbixItemResultParam.setConvertUnits(unitResult.getUnits());
            zabbixItemResultParam.setLastvalue(unitResult.getValue());
        }
    }


    /**
     * 监控数据重置
     */
    public void resettingMonitorItemInfo(QueryMonitorParam param) throws Exception {
        MwComponentLayoutInfo shareLayoutData = getLayoutInfo(param);
        //所有布局数据重新解析
        shareLayoutData.setResolved(false);
        shareLayoutData.resettingResolved();
        doUpdate(shareLayoutData);
        //mw_component_mapper_data 对应数据删除，重新请求
        LayoutItemMapperServiceImpl itemMapperService = (LayoutItemMapperServiceImpl) cmdbServiceManage.getModelService(LayoutItemMapperServiceImpl.ID);
        LayoutItemMapperInfo itemMapperInfo = new LayoutItemMapperInfo();
        itemMapperInfo.setId(param.getInstanceId());
        //数据删除
        itemMapperService.doRemove(itemMapperInfo);
    }


    /**
     * 监控布局数据重新加载
     */
    public void resettingAllMonitorItemInfo() throws Exception {
        ComponentLayoutSearchParam layoutSearchParam = new ComponentLayoutSearchParam();
        layoutSearchParam.setIgnoreDataAuth(true);
        //根据模板Id查询对应的布局数据Z
        List<MwComponentLayoutInfo> mwComponentLayoutInfos = doSelectList(layoutSearchParam);
        for(MwComponentLayoutInfo shareLayoutData : mwComponentLayoutInfos){
            //所有布局数据重新解析
            shareLayoutData.setResolved(false);
            shareLayoutData.resettingResolved();
        }
        batchUpdateLayout(mwComponentLayoutInfos);
        LayoutItemMapperServiceImpl itemMapperService = (LayoutItemMapperServiceImpl) cmdbServiceManage.getModelService(LayoutItemMapperServiceImpl.ID);
        //删除所有数据
        itemMapperService.removeAll();
    }


    /**
     * 服务器\网络设备\安全设备
     * 固定展示概览页监控数据
     */
    public void initOverViewLayout(String instanceId) throws Exception {
        QueryMonitorParam queryMonitorParam = initMonitorParam(instanceId);
        boolean isFlag = false;
        List<MwTabLayoutInfo> componentLayoutList = new ArrayList<>();
        //先判断是否是服务器\网络设备\安全设备数据
        if (isFlag) {
            MwTabLayoutInfo overViewLayout = new MwTabLayoutInfo();
            overViewLayout.setDefaultFlag(true);
            overViewLayout.setResolved(false);
            overViewLayout.setLabelId(DefaultMonitorTabEnum.overView.getId());
            List<MwLayoutDetailInfo> layout = new ArrayList<>();
            MwLayoutDetailInfo layoutDetailInfo = new MwLayoutDetailInfo();
            LayoutGrid layoutGrid = new LayoutGrid();
            layoutGrid.setX(0);
            layoutGrid.setY(0);
            layoutGrid.setW(12);
            layoutGrid.setH(2);
            layoutDetailInfo.setLayoutGrid(layoutGrid);
            layoutDetailInfo.setComponentName("CPU");
            layoutDetailInfo.setComponentType(rateLine.getItemName());
            MwLayoutItemDropInfo layoutItemDropInfo = new MwLayoutItemDropInfo();
            ItemDropInfo itemDropInfo = new ItemDropInfo();
            itemDropInfo.setChName("CPU利用率");
            itemDropInfo.setUnits("%");
            itemDropInfo.setDelay("120s");
            itemDropInfo.setValue_type(0);
            itemDropInfo.setName("CPU_UTILIZATION");
            itemDropInfo.setValuemapid("0");
            layoutItemDropInfo.setItemInfos(Arrays.asList(itemDropInfo));
            layoutDetailInfo.setDisplayData(layoutItemDropInfo);
            layout.add(layoutDetailInfo);
            overViewLayout.setLayout(layout);
            componentLayoutList.add(overViewLayout);
        }
        addDefaultOverViewTab(queryMonitorParam, componentLayoutList);
    }

    public List<MwTabLayoutInfo> getInitOverViewLayout(QueryMonitorParam queryMonitorParam) throws Exception {
        MwDeviceTypeEnum instanceDeviceType = getInstanceDeviceType(queryMonitorParam.getPath());
        List<MwTabLayoutInfo> componentLayoutList = new ArrayList<>();
        if(instanceDeviceType == null){
            return componentLayoutList;
        }

        List<String> itemNameList =  Arrays.asList(CPU.getEnglishName(),MEMORY.getEnglishName(),INTERFACE_IN.getEnglishName(),INTERFACE_OUT.getEnglishName(),DISK.getEnglishName());
        Map<String,MwZabbixItemResultParam> mapValueType = new HashMap<>();
        MWZabbixAPIResult resultItems = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.ITEMS_GET_SEARCH_BY_NAMES, queryMonitorParam.getMonitorServerId(), queryMonitorParam.getHostId(), itemNameList);
        List<MwZabbixItemResultParam> itemResult = JSONArray.parseArray(String.valueOf(resultItems.getData()), MwZabbixItemResultParam.class);
            List<String> itemIds = new ArrayList<>();
            for (MwZabbixItemResultParam node : itemResult) {
                String itemName = node.getName();
                ItemNameParam itemNameParam = itemNameFilterBracket(itemName);
                //没有分区接口
                if (!Strings.isNullOrEmpty(itemNameParam.getItemName())) {
                    mapValueType.put(itemNameParam.getItemName(),node);
                }
        }
        MwAssetsTypeMonitorLayout monitorLayout = new MwAssetsTypeMonitorLayout();
        switch (instanceDeviceType) {
            case MWSERVER:
                componentLayoutList = monitorLayout.getServerDeviceTypeLayout(mapValueType);
                break;
            case NETWORK:
            case SAFEEQUIP:
                componentLayoutList = monitorLayout.getNetWorkDeviceTypeLayout(mapValueType);
                break;
            default:
        }
        return componentLayoutList;
    }


    /**
     * 判断是否是服务器\网络设备\安全设备设备
     */
    public MwDeviceTypeEnum getInstanceDeviceType(List<String> instancePath) throws Exception {
        String networkId = SpringUtils.getPropertiesValue("base.network.groupId");
        String safeEquipId = SpringUtils.getPropertiesValue("base.safeEquip.groupId");
        String mwServerId = SpringUtils.getPropertiesValue("base.mwServer.groupId");
        if (CollectionUtils.isNotEmpty(instancePath)) {
            if (instancePath.contains(networkId)) {
                return NETWORK;
            }
            if (instancePath.contains(safeEquipId)) {
                return SAFEEQUIP;
            }
            if (instancePath.contains(mwServerId)) {
                return MWSERVER;
            }
        }
        return null;
    }

    /**
     * 导出监控详情布局数据
     */
    public void exportMonitorLayout(String modelGroupId, HttpServletResponse response) throws Exception {
        List<MwComponentLayoutInfo> allLayoutInfos = new ArrayList<>();
        ComponentLayoutSearchParam layoutSearchParam = new ComponentLayoutSearchParam();
        //导出分为两个维度：
        if (Strings.isNullOrEmpty(modelGroupId)) {
            // 1、全量导出；
            //导出所有的数据
            layoutSearchParam.setIgnoreDataAuth(true);
            //查询所有布局数据
            allLayoutInfos = doSelectList(layoutSearchParam);
        } else {
            //模型分组导出
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            Query query = new Query();
            query.addCriteria(CriteriaWrapper.where(InstanceInfo::getPath).in(modelGroupId));
            List<InstanceInfo> instanceInfos = instanceService.doListByQueryNotAuth(query);
            Set<String> templateNames = instanceInfos.stream().filter(s -> !"".equals(strValueConvert(s.getMonitorTypeId())) && intValueConvert(s.getMonitorServerId()) != 0).map(s -> s.getTemplateName()).collect(Collectors.toSet());
            layoutSearchParam = new ComponentLayoutSearchParam();
            layoutSearchParam.setIgnoreDataAuth(true);
            layoutSearchParam.setTemplateNames(new ArrayList<>(templateNames));
            //查询模型分组下的布局数据
            allLayoutInfos = doSelectList(layoutSearchParam);
        }
        allLayoutInfos = allLayoutInfos.stream().filter(s -> s.getTempName() != null && s.getAssetsId() == null).collect(Collectors.toList());
        List<Map> mapList = ListMapObjUtils.objectsToMaps(allLayoutInfos);
        List<String> fieldList = new ArrayList<>();
        List<String> fieldNameList = new ArrayList<>();
        try {
            getExcelExportFieldInfo(ComponentLayoutInfoExcelExportParam.class, fieldList, fieldNameList);
            ExportExcel.exportExcel("exportComponentLayout", "exportInstanceList", fieldNameList, fieldList, mapList, "yyyy-MM-dd HH:mm:ss", response);
        } catch (Exception e) {
            log.error("导出失败{}", e);
        }
    }

    /**
     * 导入监控详情布局数据
     */
    public void importMonitorLayout(MultipartFile file, HttpServletResponse response) throws Exception {
        String fileName = file.getOriginalFilename();
        MwUser user = SecurityUtils.getUser();
        String loginName = user.getUsername();
        if (null != fileName && (fileName.toLowerCase().endsWith(".xls") || fileName.toLowerCase().endsWith(".xlsx"))) {
            EasyExcel.read(file.getInputStream(), ComponentLayoutInfoExcelExportParam.class,
                    new ComponentLayoutExcelImportListener(response, fileName, loginName, cmdbServiceManage)).sheet().doRead();
        } else {
            log.error("没有传入正确的excel文件名", file);
        }
    }

    /**
     * 监控详情布局数据转换
     */
    public void monitorLayoutConvert() throws Exception {
        ComponentLayoutSearchParam layoutSearchParam = new ComponentLayoutSearchParam();
        layoutSearchParam.setIgnoreDataAuth(true);
        layoutSearchParam.addSubCondition(CMDBTool.getFieldName(MwComponentLayoutInfo::getAssetsId)
                , new SubCondition(CriteriaOpsType.is.name(), null));
        layoutSearchParam.addSubCondition(CMDBTool.getFieldName(MwComponentLayoutInfo::getTempName)
                , new SubCondition(CriteriaOpsType.is.name(), null));

        layoutSearchParam.addSubCondition(CMDBTool.getFieldName(MwComponentLayoutInfo::getTempId)
                , new SubCondition(CriteriaOpsType.ne.name(), null));
        layoutSearchParam.addSubCondition(CMDBTool.getFieldName(MwComponentLayoutInfo::getServerId)
                , new SubCondition(CriteriaOpsType.ne.name(), null));
        //查询所有布局数据
        List<MwComponentLayoutInfo> mwComponentLayoutInfos = doSelectList(layoutSearchParam);
        ModelTemplateServiceImpl tempService = (ModelTemplateServiceImpl) cmdbServiceManage.getModelService(ModelTemplateServiceImpl.ID);
        List<ModelTemplateInfo> allTempList = tempService.getAllList();

        Map<String, String> tempResultMap = allTempList.stream()
                .filter(t -> t.getServerTemplates() != null && !t.getServerTemplates().isEmpty()) // 过滤空列表
                .flatMap(t -> t.getServerTemplates().stream()
                        .map(st -> Map.entry(st.getServerId() + "_" + st.getServerTemplateId(), t.getTemplateName()))
                )
                .collect(Collectors.toMap(
                        Map.Entry::getKey,         // 使用 serverId + "_" + serverTemplateId 作为 key
                        Map.Entry::getValue,       // 使用 name 作为 value
                        (existingValue, newValue) -> existingValue // 如果有重复的 key，保留第一个 value
                ));

        for (MwComponentLayoutInfo layoutInfo : mwComponentLayoutInfos) {
            String tempId = layoutInfo.getTempId();
            String serverId = layoutInfo.getServerId();
            String key = serverId + "_" + tempId;
            if (tempResultMap != null && tempResultMap.containsKey(key)) {
                String tempName = tempResultMap.get(key);
                layoutInfo.setTempName(tempName);
                layoutInfo.setTempId(null);
                layoutInfo.setServerId(null);
            }
        }

        Map<String, MwComponentLayoutInfo> collect = mwComponentLayoutInfos.stream().filter(s->!Strings.isNullOrEmpty(strValueConvert(s.getTempName()))).collect(Collectors.toMap(s -> s.getTempName(), s -> s, (
                value1, value2) -> {
            return value2;
        }));
        List<MwComponentLayoutInfo> editorComponentLayoutInfos = collect.values().stream().collect(Collectors.toList());
        Set<String> editorTemplate = editorComponentLayoutInfos.stream().map(s -> s.getId()).collect(Collectors.toSet());
        Set<String> allIds = mwComponentLayoutInfos.stream().map(s -> s.getId()).collect(Collectors.toSet());
        //全部的去除修改的，剩下的为需要删除的
        allIds.removeAll(editorTemplate);
        //批量修改原始数据
        batchUpdateLayout(editorComponentLayoutInfos);
        //删除多余的（tempName重复的）布局数据
        doBatchRemove(new ArrayList<>(allIds));
    }


    private class TemplateColumWithStyle extends AbstractColumnWidthStyleStrategy {
        @Override
        protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
            if (isHead) {
                writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), 6000);
            }
        }
    }
}

